package bean.managed;

import bean.managed.util.JsfUtil;
import bean.session.RawMaterialPurchaseOrderEntityFacade;
import bean.session.SystemUserEntityFacade;
import bean.session.VendorEntityFacade;
import entity.VendorInvoiceEntity;

import bean.session.VendorInvoiceEntityFacade;
import java.util.Map;
import entity.AddressEntity;
import entity.RawMaterialPurchaseOrderEntity;
import entity.VendorEntity;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import managedbean.PdfDownload;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.servlet.http.HttpServletRequest;
import managedbean.AbstractBacking;
import org.primefaces.event.DragDropEvent;
import org.primefaces.event.SelectEvent;
import type.AddressType;
import type.RawMaterialPurchaseOrderStatus;
import type.VendorInvoiceStatus;
import util.Mailer;
import util.PDFGenerator;

@ManagedBean(name = "vendorInvoiceEntityController")
@SessionScoped
public class VendorInvoiceEntityController extends AbstractBacking implements Serializable {

    @ManagedProperty(value = "#{pdfDownload}")
    private PdfDownload pdfDownload;

    public PdfDownload getPdfDownload() {
        return pdfDownload;
    }

    public void setPdfDownload(PdfDownload pdfDownload) {
        this.pdfDownload = pdfDownload;
    }
    @EJB
    private bean.session.VendorInvoiceEntityFacade viFacade;

    public VendorInvoiceEntityFacade getViFacade() {
        return viFacade;
    }

    public void setViFacade(VendorInvoiceEntityFacade viFacade) {
        this.viFacade = viFacade;
    }
    @EJB
    private bean.session.VendorEntityFacade facade;
    @EJB
    private bean.session.RawMaterialPurchaseOrderEntityFacade rpoFacade;

    public RawMaterialPurchaseOrderEntityFacade getRpoFacade() {
        return rpoFacade;
    }

    public void setRpoFacade(RawMaterialPurchaseOrderEntityFacade rpoFacade) {
        this.rpoFacade = rpoFacade;
    }

    public VendorEntityFacade getFacade() {
        return facade;
    }

    public void setFacade(VendorEntityFacade facade) {
        this.facade = facade;
    }

    public VendorInvoiceEntityController() {
    }
    private String cName;
    private List<RawMaterialPurchaseOrderEntity> suggest = new ArrayList<RawMaterialPurchaseOrderEntity>();

    public void setSuggest(List<RawMaterialPurchaseOrderEntity> suggest) {
        this.suggest = suggest;
    }

    public List<RawMaterialPurchaseOrderEntity> getSuggest() {
        return suggest;
    }

    public void update() {
        suggest = getRpoFacade().getOrderMatchInvoice(text);
        text = "";
    }

    public String getcName() {
        return cName;
    }

    public void setcName(String cName) {
        this.cName = cName;
    }

    public void handleSelect(SelectEvent event) {
        cName = event.getObject().toString();


    }
    private RawMaterialPurchaseOrderEntity rpoSelect;

    public RawMaterialPurchaseOrderEntity getRpoSelect() {
        return rpoSelect;
    }

    public void setRpoSelect(RawMaterialPurchaseOrderEntity rpoSelect) {

        this.rpoSelect = rpoSelect;
    }
    private RawMaterialPurchaseOrderEntity selectedRpo;

    public RawMaterialPurchaseOrderEntity getSelectedRpo() {

        return selectedRpo;
    }
    private int temp = 0;

    public int getTemp() {
        return temp;
    }

    public String recreateModel() {
        selectedRpo = null;
        selectedInvoice = null;
        taxAmount = 0;
        id = "";
        dueDate = null;
        list = null;
        date1 = null;
        amount = 0;
        cost = 0;
        temp = 0;
        return "NewInvoice";
    }

    public void setTemp(int temp) {
        this.temp = temp;
    }

    public void setSelectedRpo(RawMaterialPurchaseOrderEntity selectedRpo) {
        this.selectedRpo = selectedRpo;
    }
    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public List<String> complete(String query) {
        List<String> suggestions = new ArrayList<String>();
        List<VendorEntity> list = getFacade().getUnLockedUser();
        for (VendorEntity p : list) {
            if (p.getCompanyName().startsWith(query) || p.getCompanyName().toLowerCase().startsWith(query)) {
                suggestions.add(p.getCompanyName());
            }
        }

        return suggestions;
    }
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String finish() {
        return "";
    }

    public AddressEntity getAddresse() {
        Collection<AddressEntity> li = selectedInvoice.getRawMaterialPurchaseOrder().getRmq().getVendor().getContact().getAddresses();
        for (AddressEntity a : li) {
            if (a.getType().equals(AddressType.HomeAddress)) {
                addresse = a;
                return addresse;
            }
        }
        return null;
    }

    public void setAddresse(AddressEntity addresse) {
        this.addresse = addresse;
    }
    private AddressEntity addresse;
    private AddressEntity address;

    public AddressEntity getAddress() {
        Collection<AddressEntity> li = selectedRpo.getRmq().getVendor().getContact().getAddresses();
        for (AddressEntity a : li) {
            if (a.getType().equals(AddressType.HomeAddress)) {
                return a;
            }
        }
        return null;
    }

    public void setAddress(AddressEntity address) {
        this.address = address;
    }
    private double amount;
    //date received invoice
    private Date date1;

    public Date getDate1() {
        return date1;
    }

    public void setDate1(Date date1) {
        this.date1 = date1;
    }
    private List scheduleShip;

    public List getScheduleShip() {

        scheduleShip = new ArrayList(selectedInvoice.getScheduleDetail().entrySet());
        Iterator it = scheduleShip.iterator();

        return scheduleShip;
    }

    public void setScheduleShip(List scheduleShip) {
        this.scheduleShip = scheduleShip;
    }
    private List<Schedule> droppedSchedule = new ArrayList<Schedule>();

    public List<Schedule> getDroppedSchedule() {
        return droppedSchedule;
    }

    public void setDroppedSchedule(List<Schedule> droppedSchedule) {
        this.droppedSchedule = droppedSchedule;
    }
    private Schedule selectedSchedule;

    public Schedule getSelectedSchedule() {


//        FacesContext context = FacesContext.getCurrentInstance();
//        context.addMessage(null, new FacesMessage("Invoice assigned for this shipment", "Invoice assigned for this shipment"));
        return selectedSchedule;
    }

    public void setSelectedSchedule(Schedule selectedSchedule) {
        this.selectedSchedule = selectedSchedule;


//        FacesContext context = FacesContext.getCurrentInstance();
//        context.addMessage(null, new FacesMessage("Invoice assigned for this shipment", "Invoice assigned for this shipment"));
    }
    private List<Schedule> list;

    public List<Schedule> getList() {

        List<Schedule> list = new ArrayList<Schedule>();
        scheduleShip = new ArrayList(selectedRpo.getSettleShip().entrySet());

        Iterator it = scheduleShip.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            Object key = entry.getKey();
            Date d = (Date) key;
            Object var = entry.getValue();
            Double d1 = (Double) var;

            Schedule s = new Schedule(d, d1.doubleValue());
            list.add(s);

        }
        return list;
    }
//    public boolean InvoiceHasBeenRecorded(RawMaterialPurchaseOrderEntity r,Date d){
//     Collection<VendorInvoiceEntity> v = getRpoFacade().InvoiceHasntRecoreded(r);
//       System.out.println("dddd");
//     if(v.size()==0)return false;
//     for(VendorInvoiceEntity v1:v){
//          HashMap sche = v1.getScheduleDetail();
//          if(sche.get(d)!=null)return true;
//     }
//     return false;
//    }

    public void setList(List<Schedule> list) {
        this.list = list;
    }
    private double taxAmount;

    public String create() {
        if (temp == 1) {
            FacesContext context = FacesContext.getCurrentInstance();
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, "Hmm Invoice has already been created!", "Invoice has already been created!");
            context.addMessage(null, message);
            return "";
        }
        if (droppedSchedule.size() == 0) {
            FacesContext context = FacesContext.getCurrentInstance();
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, "Wait a minute", "This Invoice is for what shipment.Be more careful please!");
            context.addMessage(null, message);
            return "";
        } else {
            HashMap ship = selectedRpo.getSettleShip();
            for (Schedule s : droppedSchedule) {
                ship.remove(s.getDate());

            }


            VendorInvoiceEntity vi = new VendorInvoiceEntity();

            HashMap sche = vi.getScheduleDetail();
            if (droppedSchedule.size() > 0) {
                for (Schedule s : droppedSchedule) {
                    sche.put(s.getDate(), s.getAmount());

                }
            }
            vi.setAmount(amount);
            vi.setStatus(VendorInvoiceStatus.pending);
            vi.setDueDate(dueDate);
            vi.setDateReceived(date1);
            vi.setExternalId(id);
            vi.setCost(cost);
            vi.setTaxAmount(taxAmount);
            vi.setRawMaterialPurchaseOrder(selectedRpo);
            vi.setCreatedBy(getCurrentUser());
            getViFacade().create(vi);
            selectedRpo.getVendorInvoices().add(vi);


            getRpoFacade().edit(selectedRpo);
            temp = 1;

            text = "";
            suggest = new ArrayList<RawMaterialPurchaseOrderEntity>();
            droppedSchedule = new ArrayList<Schedule>();
            FacesContext context = FacesContext.getCurrentInstance();
            context.addMessage(null, new FacesMessage("Invoice assigned for this shipment", "Invoice Created"));
            return "";
        }
    }
    private Date dueDate;

    public Date getDueDate() {
        return dueDate;
    }

    public void remove() {
        droppedSchedule.remove(selectedSchedule);
    }

    public void setDueDate(Date dueDate) {
        this.dueDate = dueDate;
    }
    private double cost;

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public double getCost() {
        return cost;
    }

    public void setCost(double cost) {
        this.cost = cost;
    }

    public double getTaxAmount() {
        return taxAmount;
    }

    public void setTaxAmount(double taxAmount) {
        this.taxAmount = taxAmount;
    }
    private List<RawMaterialPurchaseOrderEntity> rpos;

    public List<RawMaterialPurchaseOrderEntity> getRpos() {
//        selectedInvoice = null;
//        taxAmount = 0;
//        id = "";
//        dueDate = null;
//        date1=null;
//        amount = 0;
//        cost = 0;
//        text = "";
//        suggest = null;
        return getRpoFacade().getOrderHaventSettledInvoice();
    }

    public void setRpos(List<RawMaterialPurchaseOrderEntity> rpos) {
        this.rpos = rpos;
    }

    public RawMaterialPurchaseOrderEntity getSelect() {
        return select;
    }

    public void setSelect(RawMaterialPurchaseOrderEntity select) {
        this.select = select;
    }
    private RawMaterialPurchaseOrderEntity select;
    private RawMaterialPurchaseOrderEntity currRpo;

    public RawMaterialPurchaseOrderEntity getCurrRpo() {
        return currRpo;
    }

    public void setCurrRpo(RawMaterialPurchaseOrderEntity currRpo) {
        this.currRpo = currRpo;
    }

    public String purchaseOrderSelect(SelectEvent event) {
        currRpo = select;
        return "InvoiceOrder?faces-redirect=true";

    }
    private Collection<VendorInvoiceEntity> invoices;

    public Collection<VendorInvoiceEntity> getInvoices() {
        Collection<VendorInvoiceEntity> v = select.getVendorInvoices();

//        for(VendorInvoiceEntity v1:v){
//        
//            if(v1.getStatus().equals(VendorInvoiceStatus.settled))
//            v.remove(v1);
//        }
        return v;
    }

    public void setInvoices(Collection<VendorInvoiceEntity> invoices) {
        this.invoices = invoices;
    }
    private VendorInvoiceEntity selectedInvoice;

    public VendorInvoiceEntity getSelectedInvoice() {

//        HttpServletRequest request = (HttpServletRequest) super.getFacesContext().getExternalContext().getRequest();
//        if (request.getParameter("id") != null) {
//            System.out.println("thanhhhhhh");
//            Long id = Long.valueOf(request.getParameter("id"));
//           VendorInvoiceEntity selectedInvoice= viFacade.find(id);
//           System.out.println(selectedInvoice.getRawMaterialPurchaseOrder().getRmq().getVendor().getCompanyName()+"ggggg");
//        }   

        if (selectedInvoice == null) {

            selectedInvoice = getViFacade().getTempInvoice();



        }

        return selectedInvoice;
    }

    public void setSelectedInvoice(VendorInvoiceEntity selectedInvoice) {
      



        if (selectedInvoice.getStatus().equals(VendorInvoiceStatus.pending)) {
            selectedInvoice.setTemp(true);
            getViFacade().edit(selectedInvoice);
        }
          this.selectedInvoice = selectedInvoice;
    }

    public boolean AllInvoiceSettleForThisOrder(RawMaterialPurchaseOrderEntity re) {
        Collection<VendorInvoiceEntity> v = re.getVendorInvoices();
        if (v.size() == 0) {
            return false;
        }
        for (VendorInvoiceEntity f : v) {
            if (!f.getStatus().equals(VendorInvoiceStatus.settled)) {
                return false;
            }
        }
        return true;
    }
    private int temp1 = 0;

    public int getTemp1() {
        return temp1;
    }

    public void setTemp1(int temp1) {
        this.temp1 = temp1;
    }

    public String preparePost() {
        if (temp1 == 1) {
            FacesContext context = FacesContext.getCurrentInstance();
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, "....", "Invoice has already been posted!");
            context.addMessage(null, message);
            return "";
        }
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, new FacesMessage("Invoice " + selectedInvoice.getExternalId() + " settled", "Info sent to supplier"));
        postInvoiceViaEmail();
        selectedInvoice.setStatus(VendorInvoiceStatus.settled);

      

        selectedInvoice.setLastModifiedBy(getCurrentUser());
        selectedInvoice.setCreatedAt(new Date());
        //Collection<RawMaterialQuotationEntity> rmqs =new ArrayList<RawMaterialQuotationEntity>();
        HashMap m = selectedInvoice.getScheduleDetail();

        RawMaterialPurchaseOrderEntity r = selectedInvoice.getRawMaterialPurchaseOrder();
        Collection<VendorInvoiceEntity> v = r.getVendorInvoices();
        if (AllInvoiceSettleForThisOrder(r) && r.getSettleShip().size() == 0) {
            r.setStatus(RawMaterialPurchaseOrderStatus.settled);
            getRpoFacade().edit(r);
        }


        getViFacade().edit(selectedInvoice);
        temp1 = 1;

        return "";
    }

    public String done() {
//        selectedInvoice = null;
//        taxAmount = 0;
//        id = "";
//        dueDate = null;
//        date1=null;
//        amount = 0;
//        cost = 0;
//        text = "";
//        suggest = null;

        return "NewInvoice?faces-redirect=true";
    }

    public static class Schedule {

        private Date date;

        Schedule(Date date, double amount) {
            this.date = date;
            this.amount = amount;
        }

        public double getAmount() {
            return amount;
        }

        public void setAmount(double amount) {
            this.amount = amount;
        }

        public Date getDate() {
            return date;
        }

        public void setDate(Date date) {
            this.date = date;
        }
        private double amount;
    }
    private List scheduleDetail;

    public List getScheduleDetail() {
        scheduleDetail = new ArrayList(selectedInvoice.getScheduleDetail().entrySet());
        Iterator it = scheduleDetail.iterator();

        return scheduleDetail;
    }

    public void setScheduleDetail(List scheduleDetail) {
        this.scheduleDetail = scheduleDetail;
    }
    private Collection<VendorInvoiceEntity> invoiceList = new ArrayList<VendorInvoiceEntity>();

    public Collection<VendorInvoiceEntity> getInvoiceList() {

        if (rpoSelect != null) {
            Collection<VendorInvoiceEntity> v = rpoSelect.getVendorInvoices();
//        if(v.size()!=0){
//         for(VendorInvoiceEntity v1:v){
////        
//            if(v1.getStatus().equals(VendorInvoiceStatus.settled))
//            v.remove(v1);
//        }
//        }
            return v;

        }
        return null;
    }

    public void setInvoiceList(Collection<VendorInvoiceEntity> invoiceList) {
        this.invoiceList = invoiceList;
    }

    public boolean isPending() {
        if (selectedInvoice.getStatus().equals(VendorInvoiceStatus.pending)) {
            return true;
        }
        return false;
    }

    public void postInvoiceViaEmail() {
        System.out.println("PostInvoiceViaEmail!");
        try {
            exportToPDF();
            String path = getPdfPath();
            System.out.println(selectedInvoice.getRawMaterialPurchaseOrder().getRmq().getVendor().getContact().getEmail() + "uuuu");
            Mailer.doSend("staff.merlion@gmail.com",
                    selectedInvoice.getRawMaterialPurchaseOrder().getRmq().getVendor().getContact().getEmail(),
                    "", "New Invoice Settled By Merlion Food", "As Attached", path, null);


        } catch (Exception ex) {
            JsfUtil.addErrorMessage(ex, ex.getMessage());
            ex.printStackTrace();
        }
    }

    public void exportToPDF() {
        String path = getPdfPath();
        File file = new File(path);
        boolean exists = file.exists();
        if (!exists) {
            selectedInvoice = getViFacade().getTempInvoice();

            if (selectedInvoice == null) {
                return;
            }

            setFileName(selectedInvoice.getExternalId() + ".pdf");
            setPath(path);


            //HttpServletRequest request = (HttpServletRequest) super.getFacesContext().getExternalContext().getRequest();
            pdfDownload.generatePDFFromUrlThanh(selectedInvoice.getExternalId(), "VendorInvoice.xhtml");
        }
        selectedInvoice.setTemp(false);
        getViFacade().edit(selectedInvoice);

        System.out.println(selectedInvoice.getExternalId() + "yyyy");

    }

    public String getPdfPath() {
        String home_path = System.getProperty("user.home");

        if (home_path.indexOf("\\") > 0) {

            path = home_path + "\\" + selectedInvoice.getExternalId() + ".pdf";
            System.out.println(path + "hhh");
        } else {
            path = home_path + "/" + selectedInvoice.getExternalId() + ".pdf";
        }
        return path;
    }
    private String fileName;

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getPath() {


        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
    private String path;

    public List<VendorInvoiceEntity> getPastInvoice() {
        return pastInvoice = getViFacade().getSettledInvoice();
    }

    public void setPastInvoice(List<VendorInvoiceEntity> pastInvoice) {
        this.pastInvoice = pastInvoice;
    }
    private List<VendorInvoiceEntity> pastInvoice;
    private VendorInvoiceEntity selected;

    public VendorInvoiceEntity getSelected() {
        return selected;
    }

    public void setSelected(VendorInvoiceEntity selected) {
        this.selected = selected;
    }

    public String proceed() {
        if (selectedRpo == null) {
            FacesContext context = FacesContext.getCurrentInstance();
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_WARN, "The system cant recognise your chosen any order?", "Please choose 1 order before proceeding!");
            context.addMessage(null, message);
            return "";
        }
        return "InvoiceDetail?faces-redirect=true";
    }
    public String enddd(){
        selectedInvoice.setTemp(false);
        getViFacade().edit(selectedInvoice);
        return "PostPayment";
    }
}
